home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload Trio 2 / Shareware Overload Trio Volume 2 (Chestnut CD-ROM).ISO / dir24 / psi110g.zip / NR4.C < prev    next >
C/C++ Source or Header  |  1994-04-17  |  28KB  |  849 lines

  1. /* net/rom level 4 (transport) protocol implementation36
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  * Ported to NOS by SM0RGV, 890525.
  5.  * Inactivity timeout by WG7J, 920325
  6.  */
  7.   
  8. #include <stdio.h>
  9. #include "global.h"
  10. #ifdef NETROM
  11. #include "mbuf.h"
  12. #include "timer.h"
  13. #include "ax25.h"
  14. #include "lapb.h"
  15. #include "netrom.h"
  16. #include "nr4.h"
  17. #include "cmdparse.h"
  18. #include <ctype.h>
  19.   
  20. #undef NR4DEBUG
  21.   
  22. /* Globals: */
  23.   
  24. /* The circuit table */
  25.   
  26. struct nr4circp Nr4circuits[NR4MAXCIRC];
  27.   
  28. /* Various limits */
  29.   
  30. unsigned short Nr4window = 4;           /* Max window to negotiate */
  31. unsigned short Nr4retries = 10; /* Max retries */
  32. unsigned short Nr4qlimit = 2048;        /* Max bytes on receive queue */
  33.   
  34. /* Timers */
  35.   
  36. int32 Nr4irtt = 45000L;          /* Initial round trip time */
  37. int32 Nr4acktime = 3000L;                /* ACK delay timer */
  38. int32 Nr4choketime = 180000L;    /* CHOKEd state timeout */
  39.   
  40. static void nr4ackours __ARGS((struct nr4cb *, unsigned, int));
  41. static void nr4choke __ARGS((struct nr4cb *));
  42. static void nr4gotnak __ARGS((struct nr4cb *, unsigned));
  43. static void nr4rframe __ARGS((struct nr4cb *, unsigned, struct mbuf *));
  44.   
  45. #ifdef NR4TDISC
  46.   
  47. int32 Nr4tdiscinit = 0UL;          /* Inactivity timeout - WG7J */
  48.   
  49. int
  50. donr4tdisc(argc,argv,p)
  51. int argc;
  52. char *argv[];
  53. void *p;
  54. {
  55.     return setlong(&Nr4tdiscinit,"NR4 redundancy timer (sec)",argc,argv);
  56. }
  57.   
  58. /* Changes are if we reachs this, with 'normal' values of tdisc,
  59.  * the other end has already timed  and retried out.
  60.  * So simply reset the control block - WG7J
  61.  */
  62.   
  63. #ifdef notdef
  64. /* This doesn't seem to catch ALL cases,
  65.  * if someone can fix this, please let me know - WG7J
  66.  */
  67. void
  68. nr4_redundant(cb)
  69. struct nr4cb *cb;
  70. {
  71.     struct nr4hdr hdr;
  72.   
  73.     switch(cb->state){
  74.         case NR4STCPEND:
  75.         case NR4STCON:
  76.     /* Format disconnect request packet */
  77.             hdr.opcode = NR4OPDISRQ ;
  78.             hdr.yourindex = cb->yournum ;
  79.             hdr.yourid = cb->yourid ;
  80.   
  81.     /* Set and start timer */
  82.             cb->cdtries = 1 ;
  83.             set_timer(&cb->tcd,2 * cb->srtt);
  84.             cb->tcd.func = nr4cdtimeout ;
  85.             cb->tcd.arg = cb ;
  86.             start_timer(&cb->tcd) ;
  87.   
  88.     /* Send packet */
  89.             nr4sframe(cb->remote.node, &hdr, NULLBUF) ;
  90.   
  91.     /* Signal state change.  nr4state will take care of stopping */
  92.     /* the appropriate timers and resetting window pointers. */
  93.             nr4state(cb, NR4STDPEND) ;
  94.             break;
  95.     }
  96.   
  97. }
  98. #endif
  99.   
  100. #endif /* NR4TDISC */
  101.   
  102.   
  103.   
  104. /* This function is called when a net/rom layer four frame */
  105. /* is discovered inside a datagram addressed to us */
  106.   
  107. void
  108. nr4input(hdr,bp)
  109. struct nr4hdr *hdr;
  110. struct mbuf *bp;
  111. {
  112.     struct nr4hdr rhdr;
  113.     struct nr4cb *cb, *cb2;
  114.     int op;
  115.     unsigned window;
  116.     int acceptc;            /* indicates that connection should be accepted */
  117.     int newconn;            /* indicates that this is a new incoming */
  118.                             /* connection.  You'll see. */
  119.     int gotchoke;           /* The choke flag was set in this packet */
  120.     int i;
  121.     long t;
  122.   
  123.     op = hdr->opcode & NR4OPCODE;   /* Mask off flags */
  124.   
  125.     rhdr.flags = 0;
  126. #ifdef G8BPQ
  127.     if(G8bpq && hdr->flags & NR4_G8BPQMASK)
  128.         rhdr.flags = NR4_G8BPQMASK;
  129. #endif
  130.   
  131.     if(op == NR4OPCONRQ){                   /* process connect request first */
  132.         acceptc = 1;
  133.         newconn = 0;
  134.   
  135.         /* These fields are sent regardless of success */
  136.         rhdr.yourindex = hdr->u.conreq.myindex;
  137.         rhdr.yourid = hdr->u.conreq.myid;
  138.   
  139.         /* Check to see if we have already received a connect */
  140.         /* request for this circuit. */
  141.         if((cb = match_n4circ(hdr->u.conreq.myindex,
  142.             hdr->u.conreq.myid,hdr->u.conreq.user,hdr->u.conreq.node))
  143.         == NULLNR4CB) { /* No existing circuit if NULL */
  144.   
  145.             /* If low on memory, don't accept - WG7J */
  146.             /* Try to get a new circuit */
  147.             if((availmem() < Memthresh) || ((cb = new_n4circ()) == NULLNR4CB))
  148.                 acceptc = 0;
  149.             else {
  150.                 /* See if we have any listening sockets */
  151.                 for(i = 0; i < NR4MAXCIRC; i++){
  152.                     if((cb2 = Nr4circuits[i].ccb) == NULLNR4CB)
  153.                         continue;/* not an open circuit */
  154.                     if(cb2->state == NR4STLISTEN)
  155.                         /* A listener was found */
  156.                         break;
  157.                 }
  158.                 if(i == NR4MAXCIRC){ /* We are refusing connects */
  159.                     acceptc = 0;
  160.                     free_n4circ(cb);
  161.                 }
  162.                 if(acceptc){
  163.                     /* Load the listeners settings */
  164.                     cb->clone = cb2->clone;
  165.                     cb->user = cb2->user;
  166.                     cb->t_upcall = cb2->t_upcall;
  167.                     cb->s_upcall = cb2->s_upcall;
  168.                     cb->r_upcall = cb2->r_upcall;
  169.                     ASSIGN(cb->local,cb2->local);
  170.   
  171.                     /* Window is set to min of the offered
  172.                      * and local windows
  173.                      */
  174.                     window = hdr->u.conreq.window > Nr4window ?
  175.                     Nr4window : hdr->u.conreq.window;
  176.   
  177.                     if(init_nr4window(cb, window) == -1){
  178.                         free_n4circ(cb);
  179.                         acceptc = 0;
  180.                     } else {
  181.                         /* Set up control block */
  182.                         cb->yournum = hdr->u.conreq.myindex;
  183.                         cb->yourid = hdr->u.conreq.myid;
  184.                         memcpy(cb->remote.user,
  185.                         hdr->u.conreq.user,AXALEN);
  186.                         memcpy(cb->remote.node,
  187.                         hdr->u.conreq.node,AXALEN);
  188.                         /* Default round trip time */
  189.                         cb->srtt = Nr4irtt;
  190.                         /* set up timers, window pointers */
  191.                         nr4defaults(cb);
  192.                         cb->state = NR4STDISC;
  193.                         newconn = 1;
  194.                     } /* End if window successfully allocated */
  195.                 }   /* End if new circuit available */
  196.             } /* End of memory-low else */
  197.         } /* End if no existing circuit matching parameters */
  198.   
  199.         /* Now set up response */
  200.         if(!acceptc){
  201.             rhdr.opcode = NR4OPCONAK | NR4CHOKE;/* choke means reject */
  202.             rhdr.u.conack.myindex = 0;
  203.             rhdr.u.conack.myid = 0;
  204.             rhdr.u.conack.window = 0;
  205.         } else {
  206.             rhdr.opcode = NR4OPCONAK;
  207.             rhdr.u.conack.myindex = cb->mynum;
  208.             rhdr.u.conack.myid = cb->myid;
  209.             rhdr.u.conack.window = cb->window;
  210.         }
  211.         nr4sframe(hdr->u.conreq.node, &rhdr, NULLBUF);
  212.   
  213.         /* Why, you ask, do we wait until now for the state change
  214.          * upcall?  Well, it's like this:  if the state change triggers
  215.          * something like the mailbox to send its banner, the banner
  216.          * would have gone out *before* the conn ack if we'd done this
  217.          * in the code above.  This is what happens when you don't plan
  218.          * too well.  Learn from my mistakes :-)
  219.          */
  220.         if(newconn)
  221.             nr4state(cb, NR4STCON);/* connected (no 3-way handshake) */
  222.   
  223.         free_p(bp);
  224.         return;
  225.     } /* end connect request code */
  226.   
  227.     /* validate circuit number */
  228.     if((cb = get_n4circ(hdr->yourindex, hdr->yourid)) == NULLNR4CB){
  229.         free_p(bp);
  230.         return;
  231.     }
  232.   
  233.     /* Check for choke flag */
  234.     if(hdr->opcode & NR4CHOKE)
  235.         gotchoke = 1;
  236.     else
  237.         gotchoke = 0;
  238.   
  239.     /* Here's where the interesting stuff gets done */
  240.     switch(cb->state){
  241.         case NR4STCPEND:
  242.         switch(op){
  243.             case NR4OPCONAK:
  244.             /* Save the round trip time for later use */
  245.                 t = dur_timer(&cb->tcd) - read_timer(&cb->tcd);
  246.                 stop_timer(&cb->tcd);
  247.                 if(gotchoke){           /* connect rejected */
  248.                     cb->dreason = NR4RREFUSED;
  249.                     nr4state(cb, NR4STDISC);
  250.                     break;
  251.                 }
  252.                 cb->yournum = hdr->u.conack.myindex;
  253.                 cb->yourid = hdr->u.conack.myid;
  254.                 window = hdr->u.conack.window > Nr4window ?
  255.                 Nr4window : hdr->u.conack.window;
  256.   
  257.                 if(init_nr4window(cb, window) == -1){
  258.                     cb->dreason = NR4RRESET;
  259.                     nr4state(cb, NR4STDISC);
  260.                 } else {
  261.                     nr4defaults(cb);        /* set up timers, window pointers */
  262.   
  263.                     if(cb->cdtries == 1)    /* No retries */
  264.                     /* Use measured rtt */
  265.                         cb->srtt = t;
  266.                     else
  267.                     /* else use default */
  268.                         cb->srtt = Nr4irtt;
  269.   
  270.                     nr4state(cb, NR4STCON);
  271.                     nr4output(cb);          /* start sending anything on the txq */
  272.                 }
  273.                 break;
  274.             default:
  275.             /* We can't respond to anything else without
  276.              * Their ID and index
  277.              */
  278.                 free_p(bp);
  279.                 return;
  280.         }
  281.             break;
  282.         case NR4STCON:
  283.         switch(op){
  284.             case NR4OPDISRQ:
  285.             /* format reply packet */
  286.                 rhdr.opcode = NR4OPDISAK;
  287.                 rhdr.yourindex = cb->yournum;
  288.                 rhdr.yourid = cb->yourid;
  289.                 nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  290.                 cb->dreason = NR4RREMOTE;
  291.                 nr4state(cb, NR4STDISC);
  292.                 break;
  293.             case NR4OPINFO:
  294.             /* Do receive frame processing */
  295.                 nr4rframe(cb, hdr->u.info.txseq, bp);
  296.   
  297.             /* Reset the choke flag if no longer choked.  Processing
  298.              * the ACK will kick things off again.
  299.              */
  300.                 if(cb->choked && !gotchoke){
  301.                     stop_timer(&cb->tchoke);
  302.                     cb->choked = 0;
  303.                 }
  304.   
  305.             /* We delay processing the receive sequence number until
  306.              * now, because the ACK might pull more off the txq and send
  307.              * it, and we want the implied ACK in those frames to be right
  308.              *
  309.              * Only process NAKs if the choke flag is off.  It appears
  310.              * that NAKs should never be sent with choke on, by the way,
  311.              * but you never know, considering that there is no official
  312.              * standard for this protocol
  313.              */
  314.                 if(hdr->opcode & NR4NAK && !gotchoke)
  315.                     nr4gotnak(cb, hdr->u.info.rxseq);
  316.   
  317.             /* We always do ACK processing, too, since the NAK of one
  318.              * packet may be the implied ACK of another.  The gotchoke
  319.              * flag is used to prevent sending any new frames, since
  320.              * we are just going to purge them next anyway if this is
  321.              * the first time we've seen the choke flag.  If we are
  322.              * already choked, this call will return immediately.
  323.              */
  324.                 nr4ackours(cb, hdr->u.info.rxseq, gotchoke);
  325.   
  326.             /* If we haven't seen the choke flag before, purge the
  327.              * send window and set the timer and the flag.
  328.              */
  329.                 if(!cb->choked && gotchoke)
  330.                     nr4choke(cb);
  331.                 break;
  332.             case NR4OPACK:
  333.                 if(cb->choked && !gotchoke){
  334.                 /* clear choke if appropriate */
  335.                     stop_timer(&cb->tchoke);
  336.                     cb->choked = 0;
  337.                 }
  338.                 if(hdr->opcode & NR4NAK && !gotchoke)
  339.                     nr4gotnak(cb, hdr->u.ack.rxseq);        /* process NAKs */
  340.   
  341.                 nr4ackours(cb, hdr->u.ack.rxseq, gotchoke); /* and ACKs */
  342.   
  343.                 if(!cb->choked && gotchoke)     /* First choke seen */
  344.                     nr4choke(cb);           /* Set choke status */
  345.   
  346.                 break;
  347.         }
  348.             break;
  349.         case NR4STDPEND:
  350.         switch(op){
  351.             case NR4OPDISAK:
  352.                 cb->dreason = NR4RNORMAL;
  353.                 nr4state(cb, NR4STDISC);
  354.                 break;
  355.             case NR4OPINFO:
  356.             /* We can still do receive frame processing until
  357.              * the disconnect acknowledge arrives, but we won't
  358.              * bother to process ACKs, since we've flushed our
  359.              * transmit buffers and queue already.
  360.              */
  361.                 nr4rframe(cb, hdr->u.info.txseq, bp);
  362.                 break;
  363.         }
  364.     }       /* End switch(state) */
  365. }
  366.   
  367.   
  368. /* Send a net/rom layer 4 frame.  bp should be NULLBUF unless the frame
  369.  * type is info.
  370.  */
  371. void
  372. nr4sframe(dest, hdr, bp)
  373. char *dest;
  374. struct nr4hdr *hdr;
  375. struct mbuf *bp;
  376. {
  377.     struct mbuf *n4b;
  378.   
  379.     if((n4b = htonnr4(hdr)) == NULLBUF){
  380.         free_p(bp);
  381.         return;
  382.     } else {
  383.         append(&n4b, bp);
  384.         nr3output(dest, n4b);
  385.     }
  386. }
  387.   
  388. /* Receive frame processing */
  389. static void
  390. nr4rframe(cb, rxseq, bp)
  391. struct nr4cb *cb;
  392. unsigned rxseq;
  393. struct mbuf *bp;
  394. {
  395.     struct nr4hdr rhdr;
  396.     unsigned window = cb->window;
  397.     unsigned rxbuf = rxseq % window;
  398.     unsigned newdata = 0;           /* whether to upcall */
  399.   
  400. #ifdef NR4DEBUG
  401.     printf("Processing received info\n");
  402. #endif
  403.   
  404. #ifdef NR4TDISC
  405.     /* We received data, reset the inactivity timer - WG7J */
  406.     start_timer(&cb->tdisc);
  407. #endif
  408.   
  409.     /* If we're choked, just reset the ACK timer to blast out
  410.      * another CHOKE indication after the ackdelay
  411.      */
  412.     if(cb->qfull){
  413.         start_timer(&cb->tack);
  414.         return;
  415.     }
  416.   
  417.     /* If frame is out of sequence, it is either due to a lost frame
  418.      * or a retransmission of one seen earlier.  We do not want to NAK
  419.      * the latter, as the far end would see this as a requirement to
  420.      * retransmit the expected frame, which is probably already in the
  421.      * pipeline.  This in turn would cause another out-of-sequence
  422.      * condition, another NAK, and the process would repeat indefinitely.
  423.      * Therefore, if the frame is out-of-sequence, but within the last
  424.      * 'n' frames by sequence number ('n' being the window size), just
  425.      * accept it and discard it.  Else, NAK it if we haven't already.
  426.      *      (Modified by Rob Stampfli, kd8wk, 9 Jan 1990)
  427.      */
  428.     if(rxseq != cb->rxpected && !cb->naksent){
  429. #ifdef NR4DEBUG
  430.         printf("Frame out of sequence -- expected %u, got %u.\n",
  431.         cb->rxpected, rxseq);
  432. #endif
  433.         if(nr4between(cb->rxpected,
  434.             (rxseq + window) & NR4SEQMASK, cb->rxpastwin))
  435.             /* just a repeat of old frame -- queue ack for
  436.              * expected frame
  437.              */
  438.             start_timer(&cb->tack);
  439.         else {                  /* really bogus -- a NAKable frame */
  440.             rhdr.opcode = NR4OPACK | NR4NAK;
  441.             rhdr.yourindex = cb->yournum;
  442.             rhdr.yourid = cb->yourid;
  443.             rhdr.u.ack.rxseq = cb->rxpected;
  444.             nr4sframe(cb->remote.node,&rhdr,NULLBUF);
  445.   
  446.             /* Now make sure we don't send any more of these until
  447.              * we see some good data.  Otherwise full window
  448.              * retransmissions would result in a flurry of NAKs
  449.              */
  450.   
  451.             cb->naksent = 1;
  452.         }
  453.     }
  454.   
  455.     /* If this is a new frame, within the window, buffer it,
  456.      * then see what we can deliver
  457.      */
  458.     if(nr4between(cb->rxpected,rxseq,cb->rxpastwin)
  459.     && !cb->rxbufs[rxbuf].occupied){
  460. #ifdef NR4DEBUG
  461.         printf("Frame within window\n");
  462. #endif
  463.         cb->rxbufs[rxbuf].occupied = 1;
  464.         cb->rxbufs[rxbuf].data = bp;
  465.   
  466.         for(rxbuf = cb->rxpected % window; cb->rxbufs[rxbuf].occupied;
  467.         rxbuf = cb->rxpected % window){
  468. #ifdef NR4DEBUG
  469.             printf("Removing frame from buffer %d\n", rxbuf);
  470. #endif
  471.             newdata = 1;
  472.             cb->rxbufs[rxbuf].occupied = 0;
  473.             append(&cb->rxq,cb->rxbufs[rxbuf].data);
  474.             cb->rxbufs[rxbuf].data = NULLBUF;
  475.             cb->rxpected = (cb->rxpected + 1) & NR4SEQMASK;
  476.             cb->rxpastwin = (cb->rxpastwin + 1) & NR4SEQMASK;
  477.         }
  478.         if(newdata){
  479.             cb->naksent = 0;        /* OK to send NAKs again */
  480.             if(cb->r_upcall != NULLVFP)
  481.                 (*cb->r_upcall)(cb,len_p(cb->rxq));
  482.   
  483.             /* Now that our upcall has had a shot at the queue, */
  484.             /* see if it's past the queue length limit.  If so, */
  485.             /* go into choked mode (i.e. flow controlled). */
  486.   
  487.             if(len_p(cb->rxq) > Nr4qlimit){
  488.                 cb->qfull = 1;
  489.                 nr4ackit((void *)cb);   /* Tell `em right away */
  490.             } else
  491.                 start_timer(&cb->tack);
  492.         }
  493.     } else  /* It's out of the window or we've seen it already */
  494.         free_p(bp);
  495. }
  496.   
  497.   
  498. /* Send the transmit buffer whose sequence number is seq */
  499. void
  500. nr4sbuf(cb, seq)
  501. struct nr4cb *cb;
  502. unsigned seq;
  503. {
  504.     struct nr4hdr hdr;
  505.     struct mbuf *bufbp, *bp;
  506.     unsigned bufnum = seq % cb->window;
  507.     struct timer *t;
  508.   
  509.     /* sanity check */
  510.     if(bufnum >= cb->window){
  511. #ifdef NRDEBUG
  512.         printf("sbuf: buffer number %u beyond window\n",bufnum);
  513. #endif
  514.         return;
  515.     }
  516.   
  517.     /* Stop the ACK timer, since our sending of the frame is
  518.      * an implied ACK.
  519.      */
  520.     stop_timer(&cb->tack);
  521.   
  522.     /* Duplicate the mbuf, since we have to keep it around
  523.      * until it is acknowledged
  524.      */
  525.     bufbp = cb->txbufs[bufnum].data;
  526.   
  527.     /* Notice that we use copy_p instead of dup_p.  This is because
  528.      * a frame can still be sitting on the AX.25 send queue when it
  529.      * get acknowledged, and we don't want to deallocate its data
  530.      * before it gets sent!
  531.      */
  532.     if((bp = copy_p(bufbp, len_p(bufbp))) == NULLBUF){
  533.         free_mbuf(bp);
  534.         return;
  535.     }
  536.   
  537.     /* Prepare the header */
  538.     if(cb->qfull)                           /* are we choked? */
  539.         hdr.opcode = NR4OPINFO | NR4CHOKE;
  540.     else
  541.         hdr.opcode = NR4OPINFO;
  542.     hdr.yourindex = cb->yournum;
  543.     hdr.yourid = cb->yourid;
  544.     hdr.u.info.txseq = (unsigned char)(seq & NR4SEQMASK);
  545.     hdr.u.info.rxseq = cb->rxpected;
  546.   
  547.     /* Send the frame, then set and start the timer */
  548.     nr4sframe(cb->remote.node, &hdr, bp);
  549.   
  550.     t = &cb->txbufs[bufnum].tretry;
  551.     set_timer(t, (1 << cb->blevel) * (4 * cb->mdev + cb->srtt));
  552.     start_timer(t);
  553. }
  554.   
  555. /* Check to see if any of our frames have been ACKed */
  556.   
  557. static void
  558. nr4ackours(cb, seq, gotchoke)
  559. struct nr4cb *cb;
  560. unsigned seq;
  561. int gotchoke;   /* The choke flag is set in the received frame */
  562. {
  563.     unsigned txbuf;
  564.     struct timer *t;
  565.   
  566.     /* If we are choked, there is nothing in the send window
  567.      * by definition, so we can just return.
  568.      */
  569.     if(cb->choked)
  570.         return;
  571.   
  572.     /* Adjust seq to point to the frame being ACK'd, not the one
  573.      * beyond it, which is how it arrives.
  574.      */
  575.     seq = (seq - 1) & NR4SEQMASK;
  576.   
  577.     /* Free up all the ack'd frames, and adjust the round trip
  578.      * timing stuff
  579.      */
  580.     while (nr4between(cb->ackxpected, seq, cb->nextosend)){
  581. #ifdef NR4DEBUG
  582.         printf("Sequence # %u acknowledged\n", seq);
  583. #endif
  584.         cb->nbuffered--;
  585.         txbuf = cb->ackxpected % cb->window;
  586.         free_mbuf(cb->txbufs[txbuf].data);
  587.         cb->txbufs[txbuf].data = NULLBUF;
  588.         cb->ackxpected = (cb->ackxpected + 1) & NR4SEQMASK;
  589.   
  590.         /* Round trip time estimation, cribbed from TCP */
  591.         if(cb->txbufs[txbuf].retries == 0){
  592.             /* We only sent this one once */
  593.             int32 rtt;
  594.             int32 abserr;
  595.   
  596.             t = &cb->txbufs[txbuf].tretry;
  597.             /* get our rtt in msec */
  598.             rtt = dur_timer(t) - read_timer(t);
  599.             abserr = (rtt > cb->srtt) ? rtt - cb->srtt : cb->srtt - rtt;
  600.             cb->srtt = (cb->srtt * 7 + rtt) >> 3;
  601.             cb->mdev = (cb->mdev * 3 + abserr) >> 2;
  602.   
  603.             /* Reset the backoff level */
  604.             cb->blevel = 0;
  605.         }
  606.         stop_timer(&cb->txbufs[txbuf].tretry);
  607.     }
  608.     /* Now we recalculate tmax, the maximum number of retries for
  609.      * any frame in the window.  tmax is used as a baseline to
  610.      * determine when the window has reached a new high in retries.
  611.      * We don't want to increment blevel for every frame that times
  612.      * out, since that would lead to us backing off too fast when
  613.      * all the frame timers expired at around the same time.
  614.      */
  615.     cb->txmax = 0;
  616.   
  617.     for(seq = cb->ackxpected;
  618.         nr4between(cb->ackxpected, seq, cb->nextosend);
  619.         seq = (seq + 1) & NR4SEQMASK)
  620.         if(cb->txbufs[seq % cb->window].retries > cb->txmax)
  621.             cb->txmax = cb->txbufs[seq % cb->window].retries;
  622.   
  623.     /* This is kind of a hack.  This function is called under
  624.      * three different conditions:  either we are choked, in
  625.      * which case we return immediately, or we are not choked,
  626.      * in which case we proceed normally to keep the send
  627.      * window full, or we have seen the choke flag for the first
  628.      * time.  In the last case, gotchoke is true while cb->choked
  629.      * is false.  We want to process any acknowledgments of existing
  630.      * frames in the send window before we purge it, while at the
  631.      * same time we don't want to take anything else off the txq
  632.      * or send it out.  So, in the third case we listed, we return
  633.      * now since we've processed the ACK.
  634.      */
  635.   
  636.     if(gotchoke)
  637.         return;
  638.   
  639.     nr4output(cb);                  /* yank stuff off txq and send it */
  640.   
  641.     /* At this point, either the send window is full, or
  642.      * nr4output() didn't find enough on the txq to fill it.
  643.      * If the window is not full, then the txq must be empty,
  644.      * and we'll make a tx upcall
  645.      */
  646.     if(cb->nbuffered < cb->window && cb->t_upcall != NULLVFP)
  647.         (*cb->t_upcall)(cb, (int16)((cb->window - cb->nbuffered) * NR4MAXINFO));
  648.   
  649. }
  650.   
  651.   
  652. /* If the send window is open and there are frames on the txq,
  653.  * move as many as possible to the transmit buffers and send them.
  654.  * Return the number of frames sent.
  655.  */
  656. int
  657. nr4output(cb)
  658. struct nr4cb *cb;
  659. {
  660.     int numq, i;
  661.     struct mbuf *bp;
  662.     struct nr4txbuf *tp;
  663.   
  664.     /* Are we in the proper state? */
  665.     if(cb->state != NR4STCON || cb->choked)
  666.         return 0;               /* No sending if not connected */
  667.                     /* or if choked */
  668.   
  669.     /* See if the window is open */
  670.     if(cb->nbuffered >= cb->window)
  671.         return 0;
  672.   
  673.     numq = len_q(cb->txq);
  674.   
  675. #ifdef NR4DEBUG
  676.     printf("nr4output: %d packets on txq\n", numq);
  677. #endif
  678.   
  679.     for(i = 0; i < numq; i++){
  680.         bp = dequeue(&cb->txq);
  681. #ifdef NR4DEBUG
  682.         if(len_p(bp) > NR4MAXINFO){     /* should be checked higher up */
  683.             printf("Upper layers queued too big a buffer\n");
  684.             continue;
  685.         }
  686. #endif
  687.         /* Set up and send buffer */
  688.         tp = &cb->txbufs[cb->nextosend % cb->window];
  689.         tp->retries = 0;
  690.         tp->data = bp;
  691.         nr4sbuf(cb, cb->nextosend);
  692.   
  693.         /* Update window and buffered count */
  694.         cb->nextosend = (cb->nextosend + 1) & NR4SEQMASK;
  695.         if(++cb->nbuffered >= cb->window)
  696.             break;
  697.     }
  698.     return i;
  699. }
  700.   
  701. void
  702. nr4state(cb, newstate)
  703. struct nr4cb *cb;
  704. int newstate;
  705. {
  706.     int i;
  707.     int oldstate = cb->state;
  708.   
  709.     cb->state = newstate;
  710.   
  711.     switch(cb->state){
  712. #ifdef NR4TDISC
  713.         case NR4STCON:
  714.     /* We're connected now, start inactivity timer - WG7J */
  715.             set_timer(&cb->tdisc,Nr4tdiscinit*1000L);
  716.     /*
  717.         cb->tdisc.func = nr4_redundant ;
  718.      * Second try; the call to nr4_redundant() (see above)
  719.      * doesn't seem to catch ALL situations.
  720.      * Changes are if we reachs this, with 'normal' values of tdisc,
  721.      * the other end has already timed out and retried out.
  722.      * So simply reset the control block - WG7J
  723.      */
  724.             cb->tdisc.func = (void (*)__ARGS((void*))) reset_nr4;
  725.             cb->tdisc.arg = cb ;
  726.             start_timer(&cb->tdisc) ;
  727.             break;
  728. #endif
  729.         case NR4STDPEND:
  730.             stop_timer(&cb->tchoke);
  731. #ifdef NR4TDISC
  732.             start_timer(&cb->tdisc);
  733. #endif
  734.   
  735.         /* When we request a disconnect, we lose the contents of
  736.          * our transmit queue and buffers, but we retain our ability
  737.          * to receive any packets in transit until a disconnect
  738.          * acknowledge arrives
  739.          */
  740.             free_q(&cb->txq);
  741.   
  742.             for(i = 0; i < cb->window; i++){
  743.                 free_mbuf(cb->txbufs[i].data);
  744.                 cb->txbufs[i].data = NULLBUF;
  745.                 stop_timer(&cb->txbufs[i].tretry);
  746.             }
  747.   
  748.         /* Tidy up stats: roll the top window pointer back
  749.          * and reset nbuffered to reflect this.  Not really
  750.          * necessary, but leads to a bit more truth telling
  751.          * in the status displays.
  752.          */
  753.             cb->nextosend = cb->ackxpected;
  754.             cb->nbuffered = 0;
  755.             break;
  756.         case NR4STDISC:
  757.             stop_timer(&cb->tchoke);
  758.             stop_timer(&cb->tack);
  759.             stop_timer(&cb->tcd);
  760. #ifdef NR4TDISC
  761.             stop_timer(&cb->tdisc);
  762. #endif
  763.   
  764.         /* We don't clear the rxq, since the state change upcall
  765.          * may pull something off of it at the last minute.
  766.          */
  767.             free_q(&cb->txq);
  768.   
  769.         /* The following loop will only be executed if the
  770.          * window was set, since when the control block is
  771.          * calloc'd the window field gets a 0 in it.  This
  772.          * protects us from dereferencing an unallocated
  773.          * window buffer pointer
  774.          */
  775.             for(i = 0; i < cb->window; i++){
  776.                 free_mbuf(cb->rxbufs[i].data);
  777.                 cb->rxbufs[i].data = NULLBUF;
  778.                 free_mbuf(cb->txbufs[i].data);
  779.                 cb->txbufs[i].data = NULLBUF;
  780.                 stop_timer(&cb->txbufs[i].tretry);
  781.             }
  782.             break;
  783.     }
  784.   
  785.     if(oldstate != newstate && cb->s_upcall != NULLVFP)
  786.         (*cb->s_upcall)(cb, oldstate, newstate);
  787.   
  788.     /* We take responsibility for deleting the circuit
  789.      * descriptor.  Don't do this anywhere else!
  790.      */
  791.     if(newstate == NR4STDISC)
  792.         free_n4circ(cb);
  793. }
  794.   
  795. /* Process NAKs.  seq indicates the next frame expected by the
  796.  * NAK'ing station.
  797.  */
  798.   
  799. static void
  800. nr4gotnak(cb, seq)
  801. struct nr4cb *cb;
  802. unsigned seq;
  803. {
  804.     if(nr4between(cb->ackxpected, seq, cb->nextosend))
  805.         nr4sbuf(cb, seq);
  806. }
  807.   
  808.   
  809. /* This is called when we first get a CHOKE indication from the
  810.  * remote.  It purges the send window and sets the choke timer.
  811.  */
  812.   
  813. static void
  814. nr4choke(cb)
  815. struct nr4cb *cb;
  816. {
  817.     unsigned seq;
  818.     struct mbuf *q, *bp;
  819.     struct nr4txbuf *t;
  820.   
  821.     q = cb->txq;
  822.   
  823.     /* We purge the send window, returning the buffers to the
  824.      * txq in the proper order.
  825.      */
  826.     for(seq = (cb->nextosend - 1) & NR4SEQMASK;
  827.         nr4between(cb->ackxpected, seq, cb->nextosend);
  828.     seq = (seq - 1) & NR4SEQMASK){
  829.   
  830.         t = &cb->txbufs[seq % cb->window];
  831.         stop_timer(&t->tretry);
  832.         bp = t->data;
  833.         t->data = NULLBUF;
  834.         enqueue(&bp, q);        /* prepend this packet to the queue */
  835.         q = bp;
  836.     }
  837.   
  838.     cb->nextosend = cb->ackxpected; /* close the window */
  839.     cb->nbuffered = 0;              /* nothing in the window */
  840.     cb->txq = q;                    /* Replace the txq with the one that has */
  841.                     /* the purged packets prepended */
  842.     cb->choked = 1;         /* Set the choked flag */
  843.   
  844.     start_timer(&cb->tchoke);
  845. }
  846.   
  847. #endif /* NETROM */
  848.   
  849.